iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0
Mobile Development

攜手神隊友ChatGPT:攝護腺自我照護App開發歷程!系列 第 17

D17-Flutter x Dart視覺化魔法,攝護腺量表走勢圖_part4

  • 分享至 

  • xImage
  •  

Part1:今日目標

1.前言
2.Flutter x Dart 學習(延續昨日)

Part2:今日內容

1.前言

今天將延續昨天鐵人賽文章 D16-Flutter x Dart視覺化魔法,攝護腺量表走勢圖_part3 繼續對 Score_History_Chart_Page.dart 這個檔案做說明,期望透過對這些問題的理解,能對Flutter框架和Dart語言有更多的了解囉! (完整程式碼請參照: D15-Flutter x Dart視覺化魔法,攝護腺量表走勢圖_part2)

2.Flutter x Dart 學習(延續昨日): class _ScoreHistoryChartPageState extends State<ScoreHistoryChartPage> {}

Q5: 關於以下程式碼,class _ScoreHistoryChartPageState extends State 這邊的 extends State 為何要從 這邊繼承?

class _ScoreHistoryChartPageState extends State<ScoreHistoryChartPage> {...}

Ans: 在 Flutter 中,使用 extends State 表示 _ScoreHistoryChartPageState 這個內部狀態類別是繼承自 State 的。這種繼承關係表示 _ScoreHistoryChartPageState 將繼承 State 類別提供的功能,並且與 ScoreHistoryChartPage widget 相關聯。

具體來說,繼承自 State 的 _ScoreHistoryChartPageState 類別可以使用 widget 屬性來訪問其父級 ScoreHistoryChartPage widget 的屬性和方法,包括 data 和 dates 這些成員變數。這樣可以在內部狀態中使用這些配置參數,以及在 build 方法中訪問它們來構建 UI。

Q6: 使用latefinal的差別為何?

late List<FlSpot> _data;
late List<String> _date;

@override
void initState() {
    super.initState();
    // 初始化 _data
    _date = widget.dates;  // widget.dates.reversed.toList()
    _data = List<FlSpot>.generate(widget.data.length, (index) {
      return FlSpot(index.toDouble(), widget.data[widget.data.length - 1 - index].y);
    });
}

Ans: 在 Dart 語言中,late 和 final 都是用於變量宣告的修飾子(modifier),但它們有不同的用途和特性:
(1)final

  • final 用於宣告一個只能被賦值一次的變量。一旦被賦值,它的值就不能再被修改。
  • final 變量必須在宣告時或在構造函數中初始化。常用於宣告不會改變的常量或配置。

(2)late

  • late 是 Dart 的 null safety 特性中引入的一個修飾子。它表示該變量將在未來某個時刻被初始化,但不是在宣告時。
  • 使用 late 可以延遲變量的初始化,這在某些情境下是很有用的,例如當變量的初始化依賴於某些運行時條件時。如果嘗試在 late 變量被初始化之前訪問它,將會拋出一個錯誤。
  • late 可以與 final 一起使用,表示該變量將在未來某個時刻被初始化一次,且之後不能再被修改。

總結
final 用於宣告只能被賦值一次的變量。
late 用於宣告將在未來某個時刻被初始化的變量。
在我們的程式碼中,late 被用於 _data 和 _date 變量,表示這兩個變量將在未來某個時刻(例如在 initState 方法中)被初始化。

Q7: 關於以下generate的定義與用法為何?

void initState() {
    super.initState();
    // 這邊進行反轉數據是沒有用的,因為這邊是初始化,正式更新在下方,請搜尋下方: .reversed.toList()
    // 初始化 _data
    _date = widget.dates;  // widget.dates.reversed.toList()
    _data = List<FlSpot>.generate(widget.data.length, (index) {
      return FlSpot(index.toDouble(), widget.data[widget.data.length - 1 - index].y);
    });
  }

Ans: generateList 類的一個靜態工廠方法(static factory method),用於生成一個固定長度的列表。它需要兩個參數:

  • length:要生成的列表的長度。
  • generator:一個函數,它接受當前索引作為參數,並返回該索引對應的元素值。
  • 定義:
static List<E> generate<E>(
  int length, 
  E generator(int index)
)
  • 用法範例:
var list = List<int>.generate(5, (index) => index * index);
print(list);  // 輸出: [0, 1, 4, 9, 16]

在我們的程式碼中,generate 被用來創建一個新的 FlSpot 列表,其長度與 widget.data 相同。對於每個索引,它返回一個新的 FlSpot 對象,其 x 值為當前索引,y 值為 widget.data 中對應位置的 y 值。

Q8: 關於以下程式碼 widget.data.where 的詳細用法?

List<FlSpot> filteredData = widget.data.where((spot) {
                  // 使用 widget.dates 從 spot 的 x 座標獲取日期並解析為 DateTime
                  DateTime spotDate = DateTime.parse(widget.dates[spot.x.toInt()]);
                  // 此條件: 確保數據點的日期在選擇的日期範圍內。如果符合這個條件,則該數據點被保留
                  return spotDate.isAfter(startDate) && spotDate.isBefore(endDate.add(Duration(days: 1)));
                }).toList();

Ans: 在 Dart 中,where 是 Iterable 類的一個方法,用於過濾集合中的元素。它返回一個新的延遲計算的 Iterable,其中只包含滿足給定的條件的元素。

在我們的程式碼中,widget.data 是一個 List,因此它也是一個 Iterable。where 方法接受一個回調函數,該函數對每個元素進行評估,並返回一個布林值(Boolean)。如果回調函數返回 true,則該元素將被包含在新的 Iterable 中;如果返回 false,則該元素將被排除。

  • 詳細解析:
    • widget.data.where((spot) {...}):遍歷 widget.data 中的每個 FlSpot 對象。
    • DateTime spotDate = DateTime.parse(widget.dates[spot.x.toInt()]);:對於每個 FlSpot 對象,使用其 x 座標作為索引來從 widget.dates 中獲取日期字符串,然後將該字符串解析為 DateTime 對象。
    • return spotDate.isAfter(startDate) && spotDate.isBefore(endDate.add(Duration(days: 1)));:評估每個 FlSpot 對象的日期是否在指定的日期範圍內。如果是,則返回 true,否則返回 false。
    • toList():將過濾後的 Iterable 轉換為 List。
    • 結果: filteredData 將包含所有日期在 startDate 和 endDate 之間的 FlSpot 對象。

Q9: 承上,關於上述的程式碼 DateTime spotDate = DateTime.parse(widget.dates[spot.x.toInt()]); 的詳細用法?

Ans: 這段程式碼的主要目的是從 widget.dates 列表中獲取一個日期字符串,並將其解析為 DateTime 對象。以下是逐步分析:

  • spot.x: 是一個 FlSpot 對象,它有一個 x 屬性,代表其在 x 軸上的座標。在這個上下文中,x 的值可能是一個浮點數。
  • toInt(): 是 double 類型的一個方法,它將浮點數轉換為整數。在這裡,它被用來將 spot.x 的值轉換為整數,因為我們需要一個整數索引來從 widget.dates 列表中獲取元素。
  • widget.dates[spot.x.toInt()]: 這部分程式碼從 widget.dates 列表中獲取一個元素。該元素的索引是 spot.x 的整數值。結果是一個日期字符串。
  • DateTime.parse(...): 是 DateTime 類的一個靜態方法,它將一個符合特定格式的日期字符串解析為 DateTime 對象。在這裡,它將從 widget.dates 獲取的日期字符串解析為 DateTime 對象。
  • DateTime spotDate = ...: 解析得到的 DateTime 對象被賦值給 spotDate 變量。

總結: 這段程式碼的目的是將 FlSpot 對象的 x 屬性值作為索引,從 widget.dates 列表中獲取一個日期字符串,然後將該字符串解析為 DateTime 對象,並將其存儲在 spotDate 變量中。

Sometimes you need to be alone. Not to be lonely, but to enjoy your free time being yourself✨
有時你必須學會獨處,並不表示孤單,而是去享受做自己的時間✨


上一篇
D16-Flutter x Dart視覺化魔法,攝護腺量表走勢圖_part3
下一篇
D18-Flutter中的優雅日曆,醫療數據追蹤之旅_part1
系列文
攜手神隊友ChatGPT:攝護腺自我照護App開發歷程!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言